from typing import Type

from fastapi import APIRouter, Depends, Request

from commons.crud_base import CRUDService
from commons.eo_vo import PageQueryModel
from config.enums import BusinessType
from config.get_db import get_db
from module_admin.annotation.log_annotation import Log
from module_admin.aspect.interface_auth import CheckUserInterfaceAuth
from module_admin.service.config_service import *
from module_admin.service.login_service import LoginService, CurrentUserModel
from utils.common_util import bytes2file_response
from utils.log_util import *
from utils.page_util import *
from utils.response_util import *


def CRUDController(url_prefix: str, perm_prefix: str, oper_title: str, service: Type[CRUDService], VO: Type[BaseModel],
                   PQVO: Type[PageQueryModel]):
    route = APIRouter(prefix=url_prefix, dependencies=[Depends(LoginService.get_current_user)])

    @route.get("/list", response_model=PageResponseModel,
               dependencies=[Depends(CheckUserInterfaceAuth(f'{perm_prefix}:r'))])
    async def get_list(page_query: PQVO = Depends(PQVO.as_query), db: AsyncSession = Depends(get_db)):
        try:
            # 获取分页数据
            result = await service.get_list(db, page_query, is_page=True)
            logger.info('获取成功')
            return ResponseUtil.success(model_content=result)
        except Exception as e:
            logger.exception(e)
            return ResponseUtil.error(msg=str(e))

    @route.get("/{id}", response_model=VO, dependencies=[Depends(CheckUserInterfaceAuth(f'{perm_prefix}:r'))])
    async def query_detail(id: int, db: AsyncSession = Depends(get_db)):
        try:
            result = await service.detail(db, id)
            logger.info(f'获取id为{id}的[{oper_title}]信息成功')
            return ResponseUtil.success(data=result) if result else ResponseUtil.failure(msg='未查询到数据')
        except Exception as e:
            logger.exception(e)
            return ResponseUtil.error(msg=str(e))

    @route.post("", dependencies=[Depends(CheckUserInterfaceAuth(f'{perm_prefix}:c'))])
    @Log(title=oper_title, business_type=BusinessType.INSERT)
    async def add(request: Request, vo: VO, query_db: AsyncSession = Depends(get_db),
                  current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
        try:
            vo.create_by = current_user.user.user_name
            vo.update_by = current_user.user.user_name
        except Exception:
            pass
        try:
            result = await service.add(query_db, vo)
            if result.is_success:
                logger.info(result.message)
                return ResponseUtil.success(msg=result.message)
            else:
                logger.warning(result.message)
                return ResponseUtil.failure(msg=result.message)
        except Exception as e:
            logger.exception(e)
            return ResponseUtil.error(msg=str(e))

    @route.put("", dependencies=[Depends(CheckUserInterfaceAuth(f'{perm_prefix}:u'))])
    @Log(title=oper_title, business_type=BusinessType.UPDATE)
    async def edit(request: Request, vo: VO, query_db: AsyncSession = Depends(get_db),
                   current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
        try:
            vo.update_by = current_user.user.user_name
            vo.update_time = datetime.now()
            result = await service.edit(query_db, vo)
            if result.is_success:
                logger.info(result.message)
                return ResponseUtil.success(msg=result.message)
            else:
                logger.warning(result.message)
                return ResponseUtil.failure(msg=result.message)
        except Exception as e:
            logger.exception(e)
            return ResponseUtil.error(msg=str(e))

    @route.delete("/{ids}", dependencies=[Depends(CheckUserInterfaceAuth(f'{perm_prefix}:d'))])
    @Log(title=oper_title, business_type=BusinessType.DELETE)
    async def delete(request: Request, ids: str, query_db: AsyncSession = Depends(get_db)):
        try:
            result = await service.delete(query_db, ids)
            if result.is_success:
                logger.info(result.message)
                return ResponseUtil.success(msg=result.message)
            else:
                logger.warning(result.message)
                return ResponseUtil.failure(msg=result.message)
        except Exception as e:
            logger.exception(e)
            return ResponseUtil.error(msg=str(e))

    @route.post("/export", dependencies=[Depends(CheckUserInterfaceAuth(f'{perm_prefix}:export'))])
    @Log(title=oper_title, business_type=BusinessType.EXPORT)
    async def export_system_config_list(request: Request, vo: PQVO = Depends(PQVO.as_form),
                                        query_db: AsyncSession = Depends(get_db)):
        try:
            # 获取全量数据
            query_result = service.get_list(query_db, vo, is_page=False)
            export_result = service.export(query_result)
            logger.info('导出成功')
            return ResponseUtil.streaming(data=bytes2file_response(export_result))
        except Exception as e:
            logger.exception(e)
            return ResponseUtil.error(msg=str(e))

    return route
